import { MockDatabaseBase } from "./MockDatabaseBase";
import { CollectionConstruct, CollectionOrNull } from "./CollectionConstruct";
import { User } from "@/model/RBAC/User";
import { Role } from "@/model/RBAC/Role";
import { UserRoleTable } from "@/model/RBAC/UserRoleTable";
import { RolePermissionTable } from "@/model/RBAC/RolePermissionTable";
import { Permission } from "@/model/RBAC/Permission";
import { RecordState } from "@/model/frame/IRecordState";
import PermissionData, { IPermissionItem } from "./demo-data/PermissionData";
import { IErrorData, IResponseData } from "@/model/frame/ResponseModel";
import CryptTool from "@/utils/frame/CryptTool";

interface DBSetting {
  version: number;
}

function buildPromise(docs: Permission[], parentID = "") {
  return (item: IPermissionItem) => {
    const _id = "" + (docs.length + 1);
    docs.push({
      code: item.Code,
      ...new RecordState(_id),
      description: item.Description,
      name: item.Name,
      parentID: parentID,
      type: item.Type
    });

    if (item.Children) {
      item.Children?.forEach(buildPromise(docs, _id));
    }
  };
}

class ExampleDB extends MockDatabaseBase {
  // 数据表单
  public user: CollectionOrNull<User> = null;
  public role: CollectionOrNull<Role> = null;
  public userRoleTable: CollectionOrNull<UserRoleTable> = null;
  public permission: CollectionOrNull<Permission> = null;
  public rolePromiseTable: CollectionOrNull<RolePermissionTable> = null;

  private dbSetting: CollectionOrNull<DBSetting & RecordState> = null;

  public inited = false;

  databaseInitialize(): void {
    this.dbSetting = new CollectionConstruct<DBSetting & RecordState>(this.db, {
      name: "dbSetting",
      options: {
        indices: ["id"]
      }
    });
    this.user = new CollectionConstruct<User>(this.db, {
      name: "user",
      options: { unique: ["id", "username"], indices: ["id", "username"] }
    });
    this.role = new CollectionConstruct<Role>(this.db, {
      name: "role",
      options: { unique: ["id"], indices: ["id"] }
    });
    this.userRoleTable = new CollectionConstruct<UserRoleTable>(this.db, {
      name: "UserRoleTable",
      options: { unique: ["id"], indices: ["userID", "id"] }
    });
    this.permission = new CollectionConstruct<Permission>(this.db, {
      name: "Promise",
      options: { unique: ["id"], indices: ["id"] }
    });
    this.rolePromiseTable = new CollectionConstruct<RolePermissionTable>(
      this.db,
      {
        name: "RolePromiseTable",
        options: {
          unique: ["id"],
          indices: ["id", "roleID"]
        }
      }
    );

    // 判断数据库 version
    const setting = this.dbSetting.$.by("id", "1");
    if (!setting) {
      console.log(this.dbSetting);
      this.dbSetting.$.insert({
        ...new RecordState("1"),
        version: this.options.version
      });
      this.initDemoData();
    } else if (setting.version !== this.options.version) {
      setting.version = this.options.version;
      this.dbSetting.$.update(setting);
      this.initDemoData();
    }
    this.inited = true;
    return;
  }

  private initDemoData() {
    console.log("初始化 数据库数据");
    this.initUser();
    this.initRole();
    this.initUserRoleTable();
    this.initPromise();
    this.initRolePromiseTable();
  }

  private initUser() {
    console.log("生成超级管理员账户");
    const Admin: User = {
      ...new RecordState("1"),
      username: "admin",
      password: CryptTool.md5("admin")
    };
    this.user!.$.insert(Admin);
  }

  private initRole() {
    console.log("生成超级管理员角色");
    const Admin: Role = {
      description: "可以控制系统中所有的权限",
      name: "超级管理员",
      ...new RecordState("1")
    };
    this.role!.$.insert(Admin);
  }

  private initUserRoleTable() {
    console.log("用户角色关联");
    const doc: UserRoleTable = {
      roleID: "1",
      userID: "1",
      ...new RecordState("1")
    };
    this.userRoleTable!.$.insert(doc);
  }

  private initPromise() {
    const _docs: Permission[] = [];
    PermissionData.forEach(buildPromise(_docs));
    console.log(_docs);
    this.permission!.$.insert(_docs);
  }

  private initRolePromiseTable() {
    const _docPromise = this.permission!.$.find();
    const _docTable: RolePermissionTable[] = [];

    _docPromise.forEach(item => {
      const _id = "" + (_docTable.length + 1);
      _docTable.push({
        ...new RecordState(_id),
        promiseID: item.id,
        roleID: "1"
      });
    });

    this.rolePromiseTable!.$.insert(_docTable);
  }
}

const db = new ExampleDB("Mock", { version: 1 });

/**
 * 判断数据库已初始化的装饰器
 * @constructor
 *
 * @example
 *   @ IsDBInit
 *   UserList()
 */
export function IsDBInit(
  target: any,
  propertyKey: string | symbol,
  descriptor: PropertyDescriptor
) {
  const originalMethod = descriptor.value;
  descriptor.value = function(): IResponseData {
    if (!db.inited) {
      const _error: IErrorData = {
        error: "ServerError",
        message: "数据库未能正常初始化"
      };
      return {
        code: 500,
        data: _error
      };
    } else {
      // eslint-disable-next-line prefer-rest-params
      return originalMethod.apply(this, arguments);
    }
  };
  return descriptor;
}

export default db;
